package com.hs

import android.content.Context
import com.hs.common.bo.RegisterFingerResultDto
import com.hs.common.bo.SearchFingerResultDto
import com.hs.framework.utils.FileUtils
import com.hs.framework.utils.HexUtils
import com.za.finger.ZAAPI
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import javax.inject.Inject
import javax.inject.Singleton

/**
 * 指纹
 */
@Singleton
class ZaFingerprintHelper @Inject constructor(@ApplicationContext val context: Context) {
//0xffffffff
    private var DEV_ADDR  = 0xffffffff
    private var OXFF = 0xff
    private  val zaclient: ZAAPI by lazy {
        ZAAPI()
    }
    // 状态
    private var status : Int = 0
    // 注册中
    private var isRegister: Boolean = false
    // 搜索中
    private var isSearch: Boolean = false
    //是否空闲
    private var iscancle: Boolean = false

    private var isshowbmp: Boolean = false

    private var fpno = 0


     fun stop(){
        isRegister = false
        isSearch = false
        iscancle = false
//        status = 0
    }

    /**
     * 打开设备
     */
    suspend fun openDev() : Int{
        println("打开设备,start")
        FileUtils.writeFile("/sdcard/Android/fps.bmp", "1122343423423")
        var len = 0;
        val pParTable = IntArray(1024)
        var tryCount : Int = 3
        do {
            delay(200)
            status = zaclient.opendevice(context, 2, 0, 0, 0, 0)
            tryCount --
        }while (status != 1 && tryCount>0)

        if (status == 1 ){
            isshowbmp = true
            // 获取指纹列表
            len = zaclient.ZAZReadIndexTable(DEV_ADDR.toInt(), pParTable)
            fpno = try {
                pParTable.get(len - 1) + 1
            } catch (e: Exception) {
                0
            }
        }
        println("打开设备 end,status == ${status},fpno == ${fpno}")
        return  status;
    }

    /**
     * 关闭设备
     */
    suspend fun closeDev(){
        status = zaclient.ZAZCloseDeviceEx()
        println("关闭设备,status == ${status}")
    }

    /**
     * 获取sn
     */
    suspend fun getSn():String?{
//        println("获取设备SN")
        var ret = 0
        val msg: String
        val uuid = ByteArray(4)
        ret = zaclient.ZAZGetRandomData(DEV_ADDR.toInt(), uuid)
        msg = "UUID:" + HexUtils.toHexString(uuid)
        println("获取设备SN,${msg},ret = ${ret}")
        return ""
    }

    suspend fun getFingerInfo() {
        val pVersion = ByteArray(512)
        var msg: String
        val ret = zaclient.ZAZReadInfPage(DEV_ADDR.toInt(), pVersion)
        println("getFingerInfo 库大小:${(pVersion[4].toInt() and 0xff) * 256 + (pVersion[5].toInt() and 0xff)}")
        println( "getFingerInfo 波特率:${((pVersion[14].toInt() and 0xff) * 256 + (pVersion[15].toInt() and 0xff)) * 9600} ")
//        println( " 产品系列：" + kotlin.String(pVersion, 28, 8) ")
        val productSeries = "产品系列：" + String(pVersion.copyOfRange(28, 28 + 8))
        println("getFingerInfo ${productSeries}")
        println("getFingerInfo 软件版本  ${String(pVersion.copyOfRange(36, 36 + 8))}")
        println("getFingerInfo 厂家名称  ${String(pVersion.copyOfRange(44, 44 + 8))}")
    }

    /**
     *  注册指纹
     */
    suspend fun registerFingerprint(startFingerId : Int) : Flow<RegisterFingerResultDto> = flow{

        if (status != 1) {
            isRegister = false
            iscancle = false
            emit(RegisterFingerResultDto(result = false,  status = 500, msg = "设备状态异常,请检查${status}"))
            return@flow
        }

        if (isSearch) {
            isRegister = false
            iscancle = false
            emit(RegisterFingerResultDto(result = false,  status = 500, msg = "正在搜索中"))
            return@flow
        }

        if (startFingerId>fpno){
            fpno = startFingerId
        }

        var ret = 0
        var msg = ""
        val Image = ByteArray(256 * 288)
        val len = IntArray(1)
        var timecount = 0
        var bufferid = 1
        iscancle = true
        zaclient.ZAZSetImageSize(256 * 288)
        delay(200)
        while (iscancle) {
            ret = zaclient.ZAZGetImage(DEV_ADDR.toInt())
//            println(" getImage ret =${ret}")
            delay(100)
            if (ret == 0) {
                if (isshowbmp) {
                    ret = zaclient.ZAZUpImage(DEV_ADDR.toInt(), Image, len)
                    if (ret != 0) {
//                        msg = "上传图像失败"
                        emit(RegisterFingerResultDto(result = false,  status = 201, msg = ""))
                    }
                }
                emit(RegisterFingerResultDto(result = false,  status = 201, msg = "", imageData = Image, imageLen = len[0]))
                ///生成特征码
                ret = zaclient.ZAZGenChar(DEV_ADDR.toInt(), bufferid)
                if (ret == 0) {
                    bufferid++
                    msg += "生成特征成功 buf=$bufferid"
//                    m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
                    emit(RegisterFingerResultDto(result = false,  status = 201, msg = "生成特征成功"))
                }
                if (bufferid < 3) {
                    // 请再按一次
                    emit(RegisterFingerResultDto(result = false,  status = 200, msg = "请再按一次指纹"))
                    delay(200)
                    continue
                }
                bufferid = 0
                // 合成模板函数
                ret = zaclient.ZAZRegModule(DEV_ADDR.toInt())
                println("合成模板函数:ret=${ret}")
                if (ret != 0) {
//                    msg += "合成失败\r\n"
//                    m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
                    emit(RegisterFingerResultDto(result = false,  status = 201, msg = ""))
                    delay(500)
                    continue
                }
                //、存储模板函数(将 ModelBuffer 中的文件储存到 flash 指纹库中)
//                参数：
//                hHandle 设备句柄；
//                nAddr：0xffffffff ；
//                iBufferID：0x01、0x02
//                iPageID：模板存储到指纹库中的 ID 号
//                返回值：
//                0 为成功，其它返回值请参考错误返回码
                ret = zaclient.ZAZStoreChar(DEV_ADDR.toInt(), 1, fpno)
                println("存储模板函数:ret=${ret}")
                if (ret == 0) {
                    fpno++
                    msg += "注册成功 ID:$fpno"
//                m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
                    val tmpBuff = ByteArray(512)
                    val pageId = IntArray(1)
                    zaclient.ZAZUpChar(DEV_ADDR.toInt(), 1, tmpBuff, pageId)
//                mRegisterListener.onRegisterResult(
//                    true, tmpBuff,
//                    pageId[0], Image, len[0], fpno
//                )
//                    Boolean result,byte[] featureData,int featureLen,byte[] imageData,int imageLen,int featureId
                    emit(RegisterFingerResultDto(result = true,  status = 0, msg = "注册成功",
                       featureData = tmpBuff, featureLen = pageId[0], imageData = Image, imageLen = len[0], featureId = fpno))
                    iscancle = false
                    isRegister = false
                    return@flow
                }
                delay(500)
            } else if (ret != 2) {
//                msg = "获取图像异常 ret=$ret\r\n"
//                m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
                emit(RegisterFingerResultDto(result = false,  status = 500, msg = "获取图像异常"))
//                iscancle = false
//                isRegister = false
                return@flow
            } else {
                timecount++
//                msg = "注册指纹中\r\n请按“取消”停止当前操作\r\n获取图像中 time=$timecount\r\n"
//                m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
                emit(RegisterFingerResultDto(result = false,  status = 205, msg = "请按指纹"))
//                iscancle = false
//                isRegister = false
            }
            delay(100)
        }
        iscancle = false
        isRegister = false
        return@flow
    }

//    /***
//     *  搜索指纹
//     */
    suspend fun searchFinger() : Flow<SearchFingerResultDto> = flow {
        if (status != 1) {
            isSearch = false
            emit(SearchFingerResultDto(result = false,  status = 500, msg = "设备状态异常，请检查${status}"))
            return@flow
        }
        if (isRegister) {
            isSearch = false
            emit(SearchFingerResultDto(result = false,  status = 500, msg = "正在注册,请先完成。"))
            return@flow
        }
        var ret = 0
        var msg = ""
        val Image = ByteArray(256 * 288)
        val len = IntArray(1)
        val iMbAddress = IntArray(1)
        val iscore = IntArray(1)
        var timecount = 0
        iscancle = true
        while (iscancle) {
            delay(100)
            ret = zaclient.ZAZGetImage(DEV_ADDR.toInt())
            if (ret == 0) {
                if (isshowbmp) {
                    ret = zaclient.ZAZUpImage(DEV_ADDR.toInt(), Image, len)
                    if (ret != 0) {
    //                    msg = "上传图像失败"
    //                    m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
                        emit(SearchFingerResultDto(result = false,  status = 201, msg = "上传图像失败"))
                    }
                }
                msg = "获取图像成功\r\n"
    //            m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
    //            m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.bmpshow, len[0], 0, Image))
                ret = zaclient.ZAZGenChar(DEV_ADDR.toInt(), 1)
                if (ret != 0) {
                    msg += "生成特征失败 \r\n"
    //                m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
                    emit(SearchFingerResultDto(result = false,  status = 201, msg = "上传图像失败"))
                }
                ret = zaclient.ZAZSearch(DEV_ADDR.toInt(), 1, 0, 999, iMbAddress, iscore)
                if (ret == 0){
//                    """搜索成功  ID:${iMbAddress[0]}  得分:${iscore[0]}
//                    mListener.onRecognizeResult(true, iMbAddress[0], Image, len[0]);
//                    onRecognizeResult(boolean recognizeResult, int templateId, byte[] imageData, int dataLen)
                    emit(SearchFingerResultDto(result = true,  status = 0, msg = "搜索成功",iMbAddress[0],Image,len[0]))
                }else{
                    // 搜索失败 提示
                    emit(SearchFingerResultDto(result = false,  status = 201, msg = "找不到匹配的指纹信息，请重试。"))
                }
                delay(500)
            } else if (ret != 2) {
    //            msg = "获取图像异常 ret=$ret"
    //            m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
//                iscancle = false
//                isSearch = false
                emit(SearchFingerResultDto(result = false,  status = 201, msg = "找不到匹配的指纹信息，请重试。"))
                return@flow
            } else {
                timecount++
    //            msg = "搜索指纹中\r\n请按“取消”停止当前操作\r\n获取图像中 time=$timecount\r\n"
    //            m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
                emit(SearchFingerResultDto(result = false,  status = 201, msg = "请按指纹。"))
                delay(200)
            }
        }
    //    msg += "操作已取消"
    //    m_fEvent.sendMessage(m_fEvent.obtainMessage(MainActivity.msgshow, 0, 0, msg))
        iscancle = false
        isSearch  = false
    //      return  null
        return@flow
    }

    // 获取列表，获取图像，清空指纹

    /**
     * 获取列表 数量
     */
    suspend fun getTableSize() : Int{
        var len = 0
        val pParTable = IntArray(1024)
        len = zaclient.ZAZReadIndexTable(DEV_ADDR.toInt(), pParTable)
        return len
    }

    /**
     * 清空指纹: 情况
     */
    suspend fun clearAll() : Int{
        var ret = 0
        ret = zaclient.ZAZEmpty(DEV_ADDR.toInt())
        return  ret
    }

    /**
     * 删除模板
     */
    suspend fun deleteByFingerId(fingerId:Int) : Int{
        var ret = 0
        ret = zaclient.ZAZDelChar(DEV_ADDR.toInt(),fingerId,1)
        return  ret
    }

}